import { type Ref, ref, unref, onBeforeMount, nextTick, } from 'vue'
import { type setTableHeightParamsType, setTableHeight, setFixedColumnWidth, treeArrToList, downloadFileByBlob } from '@/common/utils'
import { exportExcelApi, getSuccessStatus } from "@/api/common"
import { ElMessage as messageUtil } from 'element-plus'
import { useRoute } from "vue-router"
import dayjs from "dayjs"

export function useTableMixin<ItemType = ObjType>(config: paramsType) {

  const {
    listApiFunc, deleteApiFunc, importApiFunc, otherSectionHeight = 0, setTableHeightExtendParams = {},
    initPageSize = 20, columns, actionList, noNeedAuthBtnNumInFixCol = 0,
    searchPanelcollapsed_after, add_before, update_before, seeDetail_before, delete_before, import_before, export_before, add_after, update_after, delete_after, query_after, search_after, reset_after, select_after, import_after, export_after,
  } = config

  const route = useRoute()
  const tableRef = ref()
  const current = ref(1)
  const size = ref(initPageSize)
  const total = ref(0)
  const filterOptions = ref<Partial<ItemType>>({})
  const tableHeight = ref<number>(200)
  const fixedColWidth = ref<number | string>('0px')
  const tableList = ref<ItemType[]>([])
  const selectedRows = ref<ItemType[]>([])
  const addRef = ref()
  const updateRef = ref()
  const detailRef = ref()
  const addDialogVisible = ref(false)
  const updateDialogVisible = ref(false)
  const detailDialogVisible = ref(false)
  const editRow = ref({} as ItemType)
  const addDialogIsFull = ref(false)
  const updateDialogIsFull = ref(false)
  const detailDialogIsFull = ref(false)
  const searchPanelHeight = ref(0)
  let firstSetTableHeigth = true
  const basicPaginationConfig = {
    pageSizes: [3, 5, 10, 20, 30, 40, 50],
    small: true,
    background: true,
    layout: 'total, sizes, prev, pager, next, jumper',
    onCurrentChange: (page: number) => { handlePaginationChange({ page }) },
    onSizeChange: (size: number) => { handlePaginationChange({ size }) },
  }

  if (actionList && columns)
    fixedColWidth.value = setFixedColumnWidth(actionList, columns, noNeedAuthBtnNumInFixCol)

  onBeforeMount(() => {
    getData()
  })

  function handleSearchPanelcollapsed(h: number) {
    searchPanelHeight.value = h
    setTableHeight({ tableHeightRef: tableHeight, otherSectionHeight: h + otherSectionHeight, ...setTableHeightExtendParams })
    searchPanelcollapsed_after && searchPanelcollapsed_after(h)
  }


  async function getData() {
    try {
      let params: PageReqParams<ItemType>
      params = { current: current.value, size: size.value, cdt: unref<any>(filterOptions) }
      const { data, code, message } = await listApiFunc(params)
      if (code == getSuccessStatus()) {
        tableList.value = data.list ? data.list : []
        total.value = data.total ? data.total : 0
        if (firstSetTableHeigth && !searchPanelHeight.value) {
          firstSetTableHeigth = false
          setTableHeight({ tableHeightRef: tableHeight, otherSectionHeight, ...setTableHeightExtendParams })
        }
        //console.log(data)
        selectedRows.value = []
        query_after && query_after()
      } else throw new Error("分页查询出错：" + message)

    } catch (error) {
      console.log(error, 'useTableMixin getData err')
    }

  }

  function handleSearch(cdt: any) {
    filterOptions.value = cdt
    if (cdt[dateRangeFieldName])
      rangeDateHandler(cdt, dateRangeFieldName, 'date')
    if (cdt[timeRangeFieldName])
      rangeDateHandler(cdt, timeRangeFieldName, 'time')
    current.value = 1
    size.value = initPageSize
    getData()
    search_after && search_after()
  }

  function handleReset() {
    filterOptions.value = {} as any
    current.value = 1
    size.value = initPageSize
    getData()
    reset_after && reset_after()
  }

  function handlePaginationChange({ page, size: s }: { page?: number, size?: number }) {
    if (page)
      current.value = page
    if (s)
      size.value = s
    getData()
  }

  function handleColumnsChange(list: any[]) {
    //console.log(list)
    if (columns) columns.value = list
  }

  async function handleAddCommit() {
    if (addRef) {
      const isSuccess = await addRef.value?.formCommit()
      if (isSuccess) {
        addDialogVisible.value = false
        messageUtil.success('新增成功')
        getData()
        add_after && add_after()
      }
    }
  }


  async function handleUpdateCommit() {
    if (updateRef) {
      const isSuccess = await updateRef.value?.formCommit()
      if (isSuccess) {
        updateDialogVisible.value = false
        messageUtil.success('更新成功')
        getData()
        update_after && update_after()
      }
    }
  }


  function handleDetailDialogClose() {
    detailDialogVisible.value = false
  }

  function handleAdd() {
    if (add_before) {
      if (!add_before()) return
    }
    addDialogVisible.value = true
    nextTick(() => {
      if (addRef.value && addRef.value?.init) addRef.value.init()
    })
  }

  function handleUpdate(row: any) {
    //console.log(row)
    editRow.value = row
    if (update_before) {
      if (!update_before()) return
    }
    updateDialogVisible.value = true
    nextTick(() => {
      if (updateRef.value && updateRef.value?.init) updateRef.value.init()
    })
  }


  function handleSeeDetail(row: any) {
    editRow.value = row;
    if (seeDetail_before) {
      if (!seeDetail_before()) return
    }
    detailDialogVisible.value = true;
    nextTick(() => {
      if (detailRef.value && detailRef.value?.init) detailRef.value.init()
    })
  }

  async function handleDelete(row: any) {
    editRow.value = row
    if (delete_before) {
      if (!delete_before()) return
    }
    if (deleteApiFunc) {
      const res = await deleteApiFunc([row.id])
      if (res && res.code) {
        messageUtil.success('删除成功')
        getData()
        delete_after && delete_after()
      }
    }
  }

  function handleSelectedRowChange(rows: any[]) {
    //  console.log(rows)   
    selectedRows.value = rows
    if (select_after) select_after()
  }

  async function handleExport() {
    //console.log({...tableRef.value.elTableInstance})
    if (export_before) {
      if (!export_before()) return
    }
    if (!selectedRows.value.length) { messageUtil.warning("请选择要导出的数据"); return }
    if (!columns) { console.log(new Error("请传入表头再执行导出！")); return }
    if (columns) {
      const header: ObjType = {}
      const cols = treeArrToList(columns.value, 'childrenCols')
      cols.forEach(v => { if (v.label != "操作" && !v.type) header[v.prop] = v.label })
      const res = await exportExcelApi({ header, list: selectedRows.value as any[], title: (route.meta.title as string) + "_" + Date.now() })
      if (downloadFileByBlob(res)) {
        selectedRows.value = []
        tableRef.value && tableRef.value.elTableInstance.clearSelection()
        export_after && export_after()
      }

    }
  }

  async function handleImport(e: any) {
    if (import_before) {
      if (!import_before(e)) return
    }
    if (importApiFunc) {
      const file: File = e.file
      if (!file.name.includes(".xls")) { messageUtil.warning("请选择excel文件导入"); return }
      const res = await importApiFunc(file)
      if (res.code == getSuccessStatus()) {
        messageUtil.success("导入成功！")
        import_after && import_after()
        handleReset()
      }
    } else { console.log(new Error("请传入导入api函数再执行导入操作！")) }
  }

  function rangeDateHandler(cdt: any, fieldName: string, type: 'date' | 'time') {
    if (Array.isArray(cdt[fieldName]) && cdt[fieldName].length >= 2) {
      const [startTime, endTime] = cdt[fieldName]
      if (type == 'date') {
        cdt.startTime = dayjs(startTime).format('YYYY-MM-DD') + ' 00:00:00'
        cdt.endTime = dayjs(endTime).format('YYYY-MM-DD') + ' 00:00:00'
      } else {
        cdt.startTime = dayjs(startTime).format('YYYY-MM-DD HH:mm:ss')
        cdt.endTime = dayjs(endTime).format('YYYY-MM-DD HH:mm:ss')
      }
      delete cdt[fieldName]
    }
  }


  return {
    basicPaginationConfig,   // 表格分页基础配置
    tableRef,    // 表格ref
    current,     // 当前页码
    size,     // 页尺寸
    total,        // 总条数
    addRef,      // 新增组件ref
    updateRef,  // 更新组件ref
    detailRef,  // 详情组件ref
    filterOptions,  // 查询条件
    getData,        // 获取页数据的方法
    tableHeight,  // 表格高度
    addDialogVisible, //新增对话框显示隐藏状态
    updateDialogVisible, //更新对话框显示隐藏状态
    detailDialogVisible, // 详情对话框显示隐藏状态
    tableList,   // 表格数据
    selectedRows,    // 选中行数据
    editRow,    // 当前编辑数据
    addDialogIsFull,     // 新增对话框是否全屏的状态
    updateDialogIsFull,  // 更新对话框是否全屏的状态
    detailDialogIsFull,  // 详情对话框是否全屏的状态
    fixedColWidth,  // 固定列列宽
    handleSearchPanelcollapsed,  //search-panel组件的 @collapsed 的处理函数
    handleSearch,   // 搜索处理函数
    handleReset,   // 重置表格数据处理函数
    handlePaginationChange,  // 处理分页器变化处理函数
    handleColumnsChange,    // 表头变化组件的处理函数
    handleAdd,     // 点击新增按钮回调
    handleUpdate,   // 点击更新按钮回调
    handleSeeDetail, // 点击详情按钮回调
    handleDelete,   // 删除处理函数
    handleSelectedRowChange,   // 表格选中行变化的回调
    handleImport,   // 导入表格处理函数
    handleExport,   // 导出表格数据处理函数
    handleAddCommit,   // 新增提交处理函数
    handleUpdateCommit,  // 更新提交处理函数
    handleDetailDialogClose, // 详情模态框关闭的处理函数
  }
}



type paramsType = {
  /**
   * 分页查询api请求函数，必选
   */
  listApiFunc: (params: PageReqParams) => Promise<PageResponseData>
  /**
   * 删除api请求函数
   */
  deleteApiFunc?: (params: IdType[]) => Promise<BasicResponseData>
  /**
   * 导入excle的api请求函数
   */
  importApiFunc?: (params: File) => Promise<BasicResponseData>
  /**
   * 表头配置。用作处理需要显示的表头以及配合actionList计算固定列宽度
   */
  columns?: Ref<TableColConfig[]>
  /**
   * 内容布局中除去表格、表格工具栏、搜索面板以外元素占据的高度，默认0
   */
  otherSectionHeight?: number
  /**
   * common/utils/setTableHeight函数的扩展参数，默认{}
   */
  setTableHeightExtendParams?: Omit<setTableHeightParamsType, ('tableHeightRef' | 'otherSectionHeight')>
  /**
   * 最初时的页尺寸，默认20
   */
  initPageSize?: number
  /**
   * 表格固定列需要控制权限的动作值列表，类型参考 @/common/utils setFixedColumnWidth 的第一个入参
   */
  actionList?: (string | string[])[]
  /**
   * 在固定列中无需授权的按钮数
   */
  noNeedAuthBtnNumInFixCol?: number
  /**
   * 查询面板折叠展开之后的回调
   */
  searchPanelcollapsed_after?: (h: number) => void
  /**
   * 打开新增模态框之前，返回true才打开
   */
  add_before?: () => boolean | void
  /**
   * 打开更新模态框之前，返回true才打开 
   */
  update_before?: () => boolean | void
  /**
  * 打开详情模态框之前，返回true才打开 
  */
  seeDetail_before?: () => boolean | void
  /**
   * 删除之前，返回true才删除
   */
  delete_before?: () => boolean | void
  /**
   * 导入excel之前，返回true才执行导入。e：文件上传事件源对象
   */
  import_before?: (e: any) => boolean | void
  /**
   * 导出excel之前，返回true才执行导出
   */
  export_before?: () => boolean | void
  /**
   * 新增成功后的回调
   */
  add_after?: () => void
  /**
   * 更新成功后的回调
   */
  update_after?: () => void
  /**
   * 删除成功后的回调
   */
  delete_after?: () => void
  /**
   * 查询成功后的回调
   */
  query_after?: () => void
  /**
   * 点击查询按钮后的回调
   */
  search_after?: () => void
  /**
   * 点击重置按钮后的回调
   */
  reset_after?: () => void
  /**
  * 表格选中行变化后的回调
  */
  select_after?: () => void
  /**
   * 导入excel成功后的回调
   */
  import_after?: () => void
  /**
   * 导出excel成功后的回调
   */
  export_after?: () => void
}

export const dateRangeFieldName = "rangeDate"
export const timeRangeFieldName = "rangeTime"